package tkaczyk.simtalk.android;

import java.util.regex.Pattern;

import tkaczyk.simtalk.message.Message;
import tkaczyk.simtalk.messenger.Messenger;
import tkaczyk.simtalk.messenger.StatusDisplay.Status;
import android.app.Application;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.util.Log;

public class SimTalkDroid extends Application implements OnSharedPreferenceChangeListener {
	private static String TAG = "std.SimTalkDroid";
	
	private Messenger messenger;
	private SharedPreferences prefs;
	private ChatAdapter adapter;

	private String remoteHost;
	private String localPort;
	private String statusMessage;

	private final Pattern portPattern = Pattern.compile("^\\d{1,5}$");
	private final Pattern hostPattern = Pattern.compile("^[-.\\w]+:\\d{1,5}$");

	private boolean connected = false;
	private boolean listening = false;
	
	@Override
	public void onCreate() {
		super.onCreate();
		Log.i(TAG, "Creating application");
		prefs = PreferenceManager.getDefaultSharedPreferences(this);
		prefs.registerOnSharedPreferenceChangeListener(this);
		messenger = new Messenger();
		adapter = new ChatAdapter(getApplicationContext());
	}

	@Override
	public void onTerminate() {
		super.onTerminate();
	}

	@Override
	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
		remoteHost = prefs.getString("remoteHost", "");
		localPort = prefs.getString("localPort", "");
		messenger.setNick(prefs.getString("nick", "Unknown"));
	}

	public void connect() {
		if (!hostPattern.matcher(this.remoteHost).matches() || !portPattern.matcher(this.localPort).matches()) {
			updateStatus(Status.DISCONNECTED, "Invalid connection parameters");
			return;
		}
		String[] remote = this.remoteHost.split(":");
		String remoteHost = remote[0];
		int remotePort = Integer.parseInt(remote[1]);
		int localPort = Integer.parseInt(this.localPort);
		if (localPort < 1 || localPort > 65535 || remotePort < 1 || remotePort > 65535) {
			updateStatus(Status.DISCONNECTED, "Invalid connection parameters");
			return;
		}
		startService(new Intent(this, ChatService.class));
		messenger.connect(remoteHost, remotePort, localPort);
	}
	
	public void listen() {
		if (portPattern.matcher(localPort).matches()) {
			int port = Integer.parseInt(localPort);
			if (port > 0 && port < 65536) {
				startService(new Intent(this, ChatService.class));
				messenger.listen(port);
				return;
			}
		}
		updateStatus(Status.DISCONNECTED, "Invalid connection parameters");
	}
	
	public void disconnect() {
		messenger.close();
		adapter.clear();
		stopService(new Intent(this, ChatService.class));
	}
	
	public void stopListening() {
		disconnect();
	}
	
	public void receiveMessage(Message msg) {
		adapter.add(msg);
	}
	
	public void sendMessage(String body) {
		Message msg = messenger.SendMessage(body);
		adapter.add(msg);
	}
	
	public void updateStatus(Status status, String statusMessage) {
		switch (status) {
		case CONNECTED:
			connected = true;
			listening = true;
			break;
		case DISCONNECTED:
			connected = false;
			listening = true;
			break;
		case LISTENING:
			listening = true;
			connected = false;
			break;
		}
	}
	
	boolean isConnected() {
		return connected;
	}
	
	boolean isListening() {
		return listening;
	}
	
	public SharedPreferences getPrefs() {
		return prefs;
	}
	
	public Messenger getMessenger() {
		return messenger;
	}

	public String getStatusMessage() {
		return statusMessage;
	}

	public ChatAdapter getAdapter() {
		return adapter;
	}
}
